#include "board.h"
#include "hotplug_manager.h"
#include "msg_manager.h"
#include "esp_log.h"

#define TAG "HOTPLUG_MANAGER"

static struct hotplug_manager_context_t hotplug_manager_context;
static struct hotplug_manager_context_t  *hotplug_manager;

int hotplug_device_register(const struct hotplug_device_t *device)
{
	const struct hotplug_device_t *temp_device = NULL;
	int free_index = -1;

	for (int i = 0; i < MAX_HOTPLUG_DEVICE_NUM; i++) {
		temp_device = hotplug_manager->device[i];
		if (temp_device && temp_device->type == device->type) {
			return -1;
		} else if (!temp_device) {
			free_index = i;
			break;
		}
	}
	if (free_index != -1 && free_index < MAX_HOTPLUG_DEVICE_NUM) {
		hotplug_manager->device[free_index] = device;
		hotplug_manager->device_num++;
	}
	return 0;
}

int hotplug_device_unregister(const struct hotplug_device_t *device)
{
	const struct hotplug_device_t *temp_device = NULL;

	for (int i = 0; i < MAX_HOTPLUG_DEVICE_NUM; i++) {
		temp_device = hotplug_manager->device[i];
		if (temp_device && temp_device->type == device->type) {
			hotplug_manager->device[i] = NULL;
			hotplug_manager->device_num--;
		}
	}
	return 0;
}

int hotplug_event_report(int device_type, int device_state)
{
	struct app_msg  msg = {0};

	msg.type = MSG_HOTPLUG_EVENT;
	msg.cmd = device_type;
	msg.value = device_state;
	ESP_LOGI(TAG, "type: %d state: %d\n", device_type, device_state);

	return msg_manager_send_async_msg(MAIN_TASK_NAME, &msg);
}

static void _hotplug_manager_work_handle(void* arg)
{
	int state = HOTPLUG_NONE;
	const struct hotplug_device_t *device = NULL;

	for (int i = 0; i < MAX_HOTPLUG_DEVICE_NUM; i++) {
		device = hotplug_manager->device[i];
		if (!device)
			continue;

		if (device->hotplug_detect) {
			state = device->hotplug_detect();
		}

		if (state != HOTPLUG_NONE) {
			if (device->fs_process) {
				if (device->fs_process(state)) {
					continue;
				}
			}
			if (device->get_type) {
				hotplug_event_report(device->get_type(), state);
			} else {
				hotplug_event_report(device->type, state);
			}
		}
	}
}

int hotplug_manager_get_state(int hotplug_device_type)
{
	int state = HOTPLUG_NONE;
	const struct hotplug_device_t *device = NULL;

	for (int i = 0; i < MAX_HOTPLUG_DEVICE_NUM; i++) {
		device = hotplug_manager->device[i];
		if (device->type == hotplug_device_type) {
			state = device->get_state();
			break;
		}
	}

	return state;
}

int hotplug_manager_init(void)
{
	if (hotplug_manager) {
        return -1;
    }

	hotplug_manager = &hotplug_manager_context;

	memset(hotplug_manager, 0, sizeof(struct hotplug_manager_context_t));

	hotplug_sdcard_init();

    esp_timer_create_args_t timer_args = {
       .callback = (esp_timer_cb_t)_hotplug_manager_work_handle,
       .arg = NULL,
       .dispatch_method = ESP_TIMER_TASK,
       .name = "hotplug_manager_work_handle",
       .skip_unhandled_events = true
    };
    esp_timer_create(&timer_args, &hotplug_manager->timer);

    esp_timer_start_periodic(hotplug_manager->timer, 1000 * 1000);

	return 0;
}
